package com.xxx.mch.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.ImmutableMap;
import com.xxx.mch.annotation.Show;
import com.xxx.mch.dao.DepartmentMapper;
import com.xxx.mch.dao.DepartmentRewardMapper;
import com.xxx.mch.dao.DepartmentTotalScoreMapper;
import com.xxx.mch.dao.PersonalRewardMapper;
import com.xxx.mch.dao.TotalScoreMapper;
import com.xxx.mch.dao.UserMapper;
import com.xxx.mch.domain.dto.DepartmentScoreStatisticsDto;
import com.xxx.mch.domain.dto.PersonScoreDto;
import com.xxx.mch.domain.dto.TotalScoreDto;
import com.xxx.mch.domain.po.Department;
import com.xxx.mch.domain.po.DepartmentReward;
import com.xxx.mch.domain.po.DepartmentTotalScore;
import com.xxx.mch.domain.po.PersonalReward;
import com.xxx.mch.domain.po.SystemConfig;
import com.xxx.mch.domain.po.TotalScore;
import com.xxx.mch.domain.po.User;
import com.xxx.mch.domain.request.DeltaUpdateRequest;
import com.xxx.mch.domain.request.QueryScoreRequest;
import com.xxx.mch.exception.BusinessException;
import com.xxx.mch.service.AwardService;
import com.xxx.mch.service.SystemConfigService;
import com.xxx.mch.service.TotalScoreService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import javax.annotation.Resource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author FengHaixin
 * @description 一句话描述该文件的用途
 * @date 2020/3/3
 */
@Slf4j
@Service
public class TotalScoreServiceImpl implements TotalScoreService
{
    public static final String DATA_FORMAT = "yyyy-MM";

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private TotalScoreMapper totalScoreMapper;

    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private DepartmentRewardMapper departmentRewardMapper;

    @Autowired
    private DepartmentTotalScoreMapper departmentTotalScoreMapper;

    @Autowired
    private PersonalRewardMapper personalRewardMapper;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private AwardService awardService;

    @Resource
    private DepartmentServiceImpl departmentService;


    @Override
    public void calculateTotalScore(TotalScore totalScore)
    {
        String month = totalScore.getMonth();
        if (StringUtils.isEmpty(month))
        {
            month = LocalDate.now().format(DateTimeFormatter.ofPattern(DATA_FORMAT));
            totalScore.setMonth(month);
        }

        Weekend<TotalScore> totalScoreWeekend = new Weekend<>(TotalScore.class);
        WeekendCriteria<TotalScore, Object> totalScoreCriteria = totalScoreWeekend.weekendCriteria();
        totalScoreCriteria.andEqualTo(TotalScore::getUid, totalScore.getUid());
        totalScoreCriteria.andEqualTo(TotalScore::getMonth, totalScore.getMonth());
        totalScoreCriteria.andEqualTo(TotalScore::getLockStatus, 1);
        TotalScore totalScore1 = totalScoreMapper.selectOneByExample(totalScoreWeekend);
        if (Objects.nonNull(totalScore1))
        {
            throw new BusinessException("当前用户月份打分功能已被锁定.");
        }
        String lockStr = totalScore.getUid() + ":" + month;
        synchronized (lockStr.intern())
        {
            //每个用户每月一条记录信息
            User user = userMapper.selectOne(new User().setUserCode(totalScore.getUid()));
            if (user == null)
            {
                throw new BusinessException("用户不存在，usercode：" + totalScore.getUid());
            }
            totalScore.setDeptId(user.getDeptId());
            TotalScore dbScore = getTotalScore(totalScore.getUid(), month);
            if (dbScore == null)
            {
                totalScore.setMonth(month);
                totalScoreMapper.insertSelective(totalScore);
            }
            else
            {
                totalScoreMapper.incrementTotalScore(totalScore);
            }
            this.updatePoints(this.getTotalScore(totalScore.getUid(), month));
            //统计下部门分，目前是基于个人的汇总的
            this.calculateDepartmentTotalScore(user.getDeptId(), month);
            log.info("积分已更新，更新信息为：{}", JSON.toJSONString(totalScore));
        }

    }


    @Override
    public List<DepartmentScoreStatisticsDto> departmentScoreStatistics(String month)
    {
        List<Department> departments = departmentMapper.selectAll();
        if (CollectionUtils.isEmpty(departments))
        {
            return Collections.emptyList();
        }
        //solar读部门数据来计算平均值
        Map<Integer, DepartmentScoreStatisticsDto> scoreMap = totalScoreMapper.selectDepartmentTotalScore(month).stream().collect(
                Collectors.toMap(DepartmentScoreStatisticsDto::getDeptId, Function.identity()));

        Map<String, SystemConfig> scoreWeight = systemConfigService.queryConfigByMenu("scoreWeight");
        BigDecimal determinationScoreWeight = scoreWeight.get("determinationScore").getValue().divide(new BigDecimal("100"), 2,
                                                                                                      RoundingMode.DOWN);
        BigDecimal allowanceScoreWeight = scoreWeight.get("allowanceScore").getValue().divide(new BigDecimal("100"), 2, RoundingMode.DOWN);

        Map<Integer, Long> userMap = departmentService.deptEmployeeNumberExcludeZero(month);
        return departments.stream().map(department -> {
            DepartmentScoreStatisticsDto departmentScoreStatisticsDto = new DepartmentScoreStatisticsDto();
            departmentScoreStatisticsDto.setDeptId(department.getId());
            departmentScoreStatisticsDto.setDeptName(department.getOrganizationName());

            if (scoreMap.containsKey(department.getId()))
            {
                DepartmentScoreStatisticsDto dbDto = scoreMap.get(department.getId());

                Optional<Long> value = Optional.ofNullable(userMap.get(departmentScoreStatisticsDto.getDeptId()));
                if (value.isPresent()) {
                    int totalNumber = Math.toIntExact(value.get());
                    BigDecimal totalScore = dbDto.getDeterminationScore().multiply(determinationScoreWeight).add(
                            dbDto.getAllowanceScore().multiply(allowanceScoreWeight)).add(
                            Objects.isNull(dbDto.getDeltaScore()) ? BigDecimal.ZERO : dbDto.getDeltaScore());
                    departmentScoreStatisticsDto.setTotalScore(
                            totalScore.divide(new BigDecimal(totalNumber), RoundingMode.HALF_UP).setScale(2, RoundingMode.DOWN));
                }
                else
                {
                    departmentScoreStatisticsDto.setTotalScore(new BigDecimal("0"));
                }
            }
            else
            {
                departmentScoreStatisticsDto.setTotalScore(new BigDecimal("0"));
            }
            return departmentScoreStatisticsDto;

        }).collect(Collectors.toList());
    }


    @Override
    public void calculateAward(String month, Integer type)
    {
        this.checkMonth(month);

        if (awardService.isConfirm(month))
        {
            throw new BusinessException("奖金已确认，无法在计算");
        }

        //计算奖金，每月1号，计算前一个月的奖金
        Weekend<TotalScore> weekend = new Weekend<>(TotalScore.class);
        WeekendCriteria<TotalScore, Object> criteria = weekend.weekendCriteria();
        criteria.andEqualTo(TotalScore::getMonth, month);
        //前一个月所有有几分信息的
        List<TotalScore> totalScores = totalScoreMapper.selectByExample(weekend);
        if (CollectionUtils.isEmpty(totalScores))
        {
            log.info("没有总分数据，查询月份：{}", month);
            return;
        }

        if (type == 1)
        {
            this.calculateAwardByDepartment(month, totalScores);
        }
        else if (type == 2)
        {
            this.calculateAwardByPersonal(month, totalScores);
        }
    }


    @Override
    public PersonScoreDto queryTotalScore(QueryScoreRequest queryScoreRequest)
    {
        TotalScore totalScore = getTotalScore(queryScoreRequest.getUid(), queryScoreRequest.getDate());
        PersonScoreDto personScoreDto = new PersonScoreDto();
        personScoreDto.setHeader(this.getHeader());
        if (totalScore == null)
        {
            return personScoreDto;
        }
        TotalScoreDto totalScoreDto = new TotalScoreDto();
        BeanUtils.copyProperties(totalScore, totalScoreDto);
        personScoreDto.getRows().add(ImmutableMap.of(totalScore.getId() + "", totalScoreDto));
        return personScoreDto;
    }


    @Override
    public TotalScore queryTotalScore(String uid, String month)
    {
        return this.getTotalScore(uid, month);
    }


    @Override
    @Transactional (rollbackFor = Exception.class)
    public void updateTotalScore(TotalScore totalScore)
    {
        int update = totalScoreMapper.updateByPrimaryKeySelective(totalScore);

        if (Objects.nonNull(totalScore.getLeaderScore()))
        {
            TotalScore newScore = new TotalScore();
            newScore.setUid(totalScore.getUid());
            newScore.setLeaderScore(totalScore.getLeaderScore());
            applicationContext.publishEvent(newScore);
        }
        log.info("更新总分成功,更新记录数：{}", update);
    }


    @Override
    public boolean isConfirm(String month)
    {
        Weekend<DepartmentReward> weekend = new Weekend<>(DepartmentReward.class);
        WeekendCriteria<DepartmentReward, Object> criteria = weekend.weekendCriteria();
        criteria.andEqualTo(DepartmentReward::getMonth, month);
        return departmentRewardMapper.selectCount(new DepartmentReward().setMonth(month).setConfirm(1)) > 0;

    }


    @Override
    public void confirm(String month)
    {
        Weekend<DepartmentReward> weekend = new Weekend<>(DepartmentReward.class);
        WeekendCriteria<DepartmentReward, Object> criteria = weekend.weekendCriteria();
        criteria.andEqualTo(DepartmentReward::getMonth, month);
        departmentRewardMapper.updateByExampleSelective(new DepartmentReward().setConfirm(1), weekend);
    }


    @Override
    public BigDecimal queryAccumulativePoints(String uid)
    {
        Weekend<TotalScore> weekend = new Weekend<>(TotalScore.class);
        WeekendCriteria<TotalScore, Object> criteria = weekend.weekendCriteria();
        criteria.andCondition("substr(month, 1,4) = " + LocalDate.now().getYear());
        criteria.andEqualTo(TotalScore::getUid, uid);
        List<TotalScore> totalScores = totalScoreMapper.selectByExample(weekend);
        if (CollectionUtils.isEmpty(totalScores))
        {
            return BigDecimal.ZERO;
        }
        return totalScores.stream().map(TotalScore::getPoints).reduce(BigDecimal.ZERO, BigDecimal::add);
    }


    @Override
    @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void deltaUpdate(DeltaUpdateRequest request)
    {
        TotalScore totalScore = totalScoreMapper.selectByPrimaryKey(request.getId());
        if (Objects.isNull(totalScore))
        {
            throw new BusinessException("不存在id：" + request.getId());
        }

        if (awardService.isConfirm(totalScore.getMonth()))
        {
            throw new BusinessException("奖金已确认，不能再次修改");
        }

        //TODO 具有某种权限才能改, 查权限
        boolean hasAuth = true;
        if (hasAuth)
        {
            BeanUtils.copyProperties(request, totalScore);
            totalScoreMapper.updateByPrimaryKeySelective(totalScore);
            this.updatePoints(totalScore);
            DepartmentTotalScore departmentTotalScore = new DepartmentTotalScore();
            departmentTotalScore.setMonth(totalScore.getMonth());
            departmentTotalScore.setDeptId(totalScore.getDeptId());
            DepartmentTotalScore dbScore = departmentTotalScoreMapper.selectOne(departmentTotalScore);
            if (Objects.nonNull(dbScore))
            {
                dbScore.setDeltaScore(request.getDeltaScore());
                departmentTotalScoreMapper.updateByPrimaryKeySelective(dbScore);
            }
            else
            {
                departmentTotalScore.setDeltaScore(request.getDeltaScore());
                departmentTotalScoreMapper.insertSelective(departmentTotalScore);
            }
        }
        else
        {
            throw new BusinessException("没有权限修改");
        }
    }


    private void calculateDepartmentTotalScore(Integer deptId, String month)
    {
        Weekend<TotalScore> weekend = new Weekend<>(TotalScore.class);
        WeekendCriteria<TotalScore, Object> criteria = weekend.weekendCriteria();
        criteria.andEqualTo(TotalScore::getDeptId, deptId);
        criteria.andEqualTo(TotalScore::getMonth, month);
        List<TotalScore> totalScores = totalScoreMapper.selectByExample(weekend);
        if (CollectionUtils.isEmpty(totalScores))
        {
            return;
        }

        totalScores.stream().map(score -> {
            DepartmentTotalScore departmentTotalScore = new DepartmentTotalScore();
            BeanUtils.copyProperties(score, departmentTotalScore);
            departmentTotalScore.setId(null);
            departmentTotalScore.setCreatedTime(null);
            departmentTotalScore.setLatestUpdatedTime(null);
            departmentTotalScore.setDeltaScore(new BigDecimal(0));
            return departmentTotalScore;
        }).reduce(this::add).ifPresent(summaryTotalScore -> {
            DepartmentTotalScore query = new DepartmentTotalScore();
            query.setDeptId(deptId);
            query.setMonth(month);
            DepartmentTotalScore dbScore = departmentTotalScoreMapper.selectOne(query);
            if (Objects.isNull(dbScore))
            {
                log.info("创建部门奖金： " + summaryTotalScore);
                departmentTotalScoreMapper.insertSelective(summaryTotalScore);
            }
            else
            {
                log.info("更新部门奖金： " + summaryTotalScore);
                summaryTotalScore.setId(dbScore.getId());
                departmentTotalScoreMapper.updateByPrimaryKeySelective(summaryTotalScore);
            }
        });

    }


    private DepartmentTotalScore add(DepartmentTotalScore a, DepartmentTotalScore b)
    {
        DepartmentTotalScore departmentTotalScore = new DepartmentTotalScore();
        departmentTotalScore.setId(a.getId());
        departmentTotalScore.setDeptId(a.getDeptId());
        departmentTotalScore.setMonth(a.getMonth());
        departmentTotalScore.setAllowanceScore(a.getAllowanceScore().add(b.getAllowanceScore()));
        departmentTotalScore.setDeterminationScore(a.getDeterminationScore().add(b.getDeterminationScore()));
        departmentTotalScore.setDeltaScore(a.getDeltaScore().add(b.getDeltaScore()));
        departmentTotalScore.setMoney(a.getMoney().add(b.getMoney()));
        departmentTotalScore.setPoints(a.getPoints().add(b.getPoints()));

        return departmentTotalScore;
    }

    private TotalScore getTotalScore(String uid, String month)
    {


        Weekend<TotalScore> weekend = new Weekend<>(TotalScore.class);
        WeekendCriteria<TotalScore, Object> criteria = weekend.weekendCriteria();
        criteria.andEqualTo(TotalScore::getUid, uid);
        criteria.andEqualTo(TotalScore::getMonth, month);

        return totalScoreMapper.selectOneByExample(weekend);
    }


    private void updatePoints(TotalScore dbScore)
    {
        List<SystemConfig> pointsConfig = systemConfigService.queryConfigByType("points");
        if (CollectionUtils.isEmpty(pointsConfig))
        {
            throw new BusinessException("积分配置信息不存在");
        }
        SystemConfig pointConfig = pointsConfig.get(0);
        Map<String, SystemConfig> scoreWeight = systemConfigService.queryConfigByMenu("scoreWeight");
        BigDecimal determinationScoreWeight = scoreWeight.get("determinationScore").getValue().divide(new BigDecimal("100"), 2,
                                                                                                      RoundingMode.DOWN);
        BigDecimal allowanceScoreWeight = scoreWeight.get("allowanceScore").getValue().divide(new BigDecimal("100"), 2, RoundingMode.DOWN);

        BigDecimal totalScore = dbScore.getDeterminationScore().multiply(determinationScoreWeight).add(
                dbScore.getAllowanceScore().multiply(allowanceScoreWeight)).add(
                Objects.isNull(dbScore.getDeltaScore()) ? BigDecimal.ZERO : dbScore.getDeltaScore());

        if (totalScore.compareTo(pointConfig.getValue()) > 0)
        {
            BigDecimal points = totalScore.subtract(pointConfig.getValue());
            dbScore.setPoints(points);
            totalScoreMapper.updateByPrimaryKeySelective(dbScore);
        }
        else
        {
            dbScore.setPoints(new BigDecimal(0));
            totalScoreMapper.updateByPrimaryKeySelective(dbScore);
        }
    }


    private List<SystemConfig> getWeightConfigs()
    {
        List<SystemConfig> weightConfig = systemConfigService.queryConfigByType("weight");
        if (CollectionUtils.isEmpty(weightConfig))
        {
            throw new BusinessException("积分权重配置信息不存在");
        }
        return weightConfig;
    }


    private List<String> getHeader()
    {
        List<Item> list = new ArrayList<>();

        Map<String, BigDecimal> configMap = this.getWeightConfigs().stream().collect(
                Collectors.toMap(SystemConfig::getType, SystemConfig::getValue));
        ReflectionUtils.doWithLocalFields(TotalScoreDto.class, field -> {
            Show annotation = field.getAnnotation(Show.class);
            if (annotation == null)
            {
                throw new BusinessException("没有注解@Show");
            }
            BigDecimal rate = configMap.get(field.getName());
            String name = annotation.name();
            if (rate != null)
            {
                name = name + "(" + rate.intValue() + "%)";
            }
            list.add(new Item(annotation.order(), name));
        });
        Collections.sort(list);

        return list.stream().map(Item::getName).collect(Collectors.toList());
    }


    private void checkMonth(String month)
    {
        try
        {
            ZonedDateTime instant = new SimpleDateFormat(DATA_FORMAT).parse(month).toInstant().atZone(ZoneId.systemDefault());
            LocalDate requestDate = LocalDate.from(instant);
            LocalDate nowMonth = LocalDate.now();
            if (requestDate.getYear() > nowMonth.getYear())
            {
                throw new BusinessException("只能查询当前月份之前的数据");
            }
            if ((requestDate.getYear() == nowMonth.getYear()) && requestDate.getMonth().getValue() > nowMonth.getMonth().getValue())
            {
                throw new BusinessException("只能查询当前月份之前的数据");
            }
        }
        catch (ParseException e)
        {
            throw new BusinessException("日期格式错误，正确格式为：yyyy-MM");
        }

    }


    private void calculateAwardByDepartment(String month, List<TotalScore> totalScores)
    {
        Map<String, SystemConfig> scoreWeight = systemConfigService.queryConfigByMenu("scoreWeight");
        BigDecimal determinationScoreWeight = scoreWeight.get("determinationScore").getValue().divide(new BigDecimal("100"), 2,
                                                                                                      RoundingMode.DOWN);
        BigDecimal allowanceScoreWeight = scoreWeight.get("allowanceScore").getValue().divide(new BigDecimal("100"), 2, RoundingMode.DOWN);
        totalScores.stream().collect(Collectors.groupingBy(TotalScore::getDeptId)).forEach((deptId, deptScoreList) -> {
            DepartmentReward reward = new DepartmentReward().setDeptId(deptId).setMonth(month);
            DepartmentReward departmentReward = departmentRewardMapper.selectOne(reward);
            if (departmentReward == null || Objects.isNull(departmentReward.getDeptReward()))
            {
                log.warn("部门{}在{}月奖金未设置，暂不计算奖金", deptId, month);
                return;
            }
            BigDecimal score = deptScoreList.stream()
                                            .map(totalScore -> {
                                                if (Objects.isNull(totalScore.getDeltaScore()))
                                                {
                                                    totalScore.setDeltaScore(new BigDecimal(0));
                                                }
                                                return totalScore.getDeltaScore()
                                                                         .add(totalScore.getDeterminationScore()
                                                                                        .multiply(determinationScoreWeight)
                                                                                        .add(totalScore.getAllowanceScore()
                                                                                                       .multiply(allowanceScoreWeight)));
                                            })
                                            .reduce(BigDecimal::add)
                                            .orElse(new BigDecimal(0));
            log.info("部门Id：{}, 部门总分: {}", deptId, score);
            //每分价值
            BigDecimal avg = (score.compareTo(new BigDecimal(0)) > 0) ? departmentReward.getDeptReward().multiply(
                    departmentReward.getCoefficient()).divide(score, 5, RoundingMode.HALF_UP) : new BigDecimal(0);
            BigDecimal departmentMoney = deptScoreList.stream().map(singleScore -> {
                singleScore.setMoney(singleScore.getDeltaScore()
                        .add(singleScore.getDeterminationScore()
                                .multiply(determinationScoreWeight)
                                .add(singleScore.getAllowanceScore()
                                        .multiply(allowanceScoreWeight))).multiply(avg).setScale(2, RoundingMode.HALF_UP));
                totalScoreMapper.updateByPrimaryKeySelective(singleScore);
                log.info("个人奖金已更新：{}", JSON.toJSONString(singleScore));
                return singleScore.getMoney();
            }).reduce(BigDecimal::add).orElse(new BigDecimal(0));
            this.addToDepartment(deptId, month, departmentMoney);

        });
    }


    private void calculateAwardByPersonal(String month, List<TotalScore> totalScores)
    {
        Weekend<PersonalReward> personalRewardWeekend = new Weekend<>(PersonalReward.class);
        WeekendCriteria<PersonalReward, Object> personalRewardCriteria = personalRewardWeekend.weekendCriteria();
        personalRewardCriteria.andEqualTo(PersonalReward::getMonth, month);
        List<PersonalReward> personalRewards = personalRewardMapper.selectByExample(personalRewardWeekend);
        if (CollectionUtils.isEmpty(personalRewards))
        {
            log.info("没有奖金系数数据，查询月份：{}", month);
            return;
        }

        Map<String, SystemConfig> scoreWeight = systemConfigService.queryConfigByMenu("scoreWeight");
        BigDecimal determinationScoreWeight = scoreWeight.get("determinationScore").getValue().divide(new BigDecimal("100"), 2,
                                                                                                      RoundingMode.DOWN);
        BigDecimal allowanceScoreWeight = scoreWeight.get("allowanceScore").getValue().divide(new BigDecimal("100"), 2, RoundingMode.DOWN);
        Map<String, PersonalReward> personalRewardMap = personalRewards.stream().collect(
                Collectors.toMap(PersonalReward::getUid, Function.identity()));
        BigDecimal totalAWard = personalRewards.get(0).getTotalAward();
        BigDecimal coefficient = totalScores.stream().map(singleScore -> {

            BigDecimal total = singleScore.getDeltaScore().add(singleScore.getDeterminationScore()
                                                                          .multiply(determinationScoreWeight)
                                                                          .add(singleScore.getAllowanceScore()
                                                                                          .multiply(allowanceScoreWeight)));
            return total.multiply(personalRewardMap.get(singleScore.getUid()).getCoefficient());
        }).reduce(BigDecimal.ZERO, BigDecimal::add);

        totalScores.forEach(singleScore -> {
            PersonalReward personalReward = personalRewardMap.get(singleScore.getUid());
            if (Objects.isNull(personalReward))
            {
                return;
            }

            BigDecimal total = singleScore.getDeltaScore().add(singleScore.getDeterminationScore()
                                                                          .multiply(determinationScoreWeight)
                                                                          .add(singleScore.getAllowanceScore()
                                                                                          .multiply(allowanceScoreWeight)));

            BigDecimal divide = total.multiply(personalReward.getCoefficient()).divide(coefficient, 5, RoundingMode.HALF_UP);
            singleScore.setMoney(divide.multiply(totalAWard).setScale(2, RoundingMode.HALF_UP));
            totalScoreMapper.updateByPrimaryKeySelective(singleScore);
            log.info("奖金已更新：{}", JSON.toJSONString(singleScore));
        });

        totalScores.stream().collect(Collectors.groupingBy(TotalScore::getDeptId)).forEach((deptId, deptScoreList) -> {
            BigDecimal departmentMoney = deptScoreList.stream().map(TotalScore::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
            this.addToDepartment(deptId, month, departmentMoney);
        });
    }


    private void addToDepartment(Integer deptId, String month, BigDecimal departmentMoney)
    {
        Weekend<DepartmentTotalScore> weekend = new Weekend<>(DepartmentTotalScore.class);
        WeekendCriteria<DepartmentTotalScore, Object> criteria = weekend.weekendCriteria();
        criteria.andEqualTo(DepartmentTotalScore::getDeptId, deptId);
        criteria.andEqualTo(DepartmentTotalScore::getMonth, month);

        DepartmentTotalScore departmentTotalScore = new DepartmentTotalScore();
        departmentTotalScore.setMoney(departmentMoney);
        log.info("更新部门奖金：deptId = {}, month = {} , departmentMoney = {}", deptId, month, departmentMoney);
        departmentTotalScoreMapper.updateByExampleSelective(departmentTotalScore, weekend);

    }


    @Data
    private static class Item implements Comparable<Item>
    {
        private int order;

        private String name;


        Item(int order, String name)
        {
            this.order = order;
            this.name = name;
        }


        @Override
        public int compareTo(Item o)
        {
            return Integer.compare(this.order, o.order);
        }
    }
}